#include "client_func.h"

// 接收文件
int download_file(int remote_fd)
{
    int ret;
    int data_len;
    char buf[1000]={0};

    struct timeval start, end;
    gettimeofday(&start, NULL);
    

    // 1. 接收文件名
    recv_n(remote_fd, &data_len, 4); // 接收文件名长度
    recv_n(remote_fd, buf, data_len); // 接收文件名
    int fd = open(buf,O_RDWR|O_CREAT,0666); // 创建新文件

    // 2. 接收文件大小
    off_t file_size;
    recv_n(remote_fd, &data_len, 4);
    recv_n(remote_fd, &file_size, sizeof(file_size));

    // 3. 接收文件内容，使用splice
    int pipefd[2] = {0};
    pipe(pipefd);
    off_t download_size = 0, last_size = 0, slipce_size;
    slipce_size = data_len / 10000; // 文件0.01%大小
    off_t splice_byte;
    off_t remain_size = 32768;

    while(download_size < file_size)
    {
        if (remain_size > (file_size - download_size))
        {
            remain_size = file_size - download_size;
        }
        // 接收文件数据到管道
        splice_byte = splice(remote_fd, NULL, pipefd[1], NULL, remain_size, SPLICE_F_MOVE | SPLICE_F_MORE);
        // 将接收到的数据从管道写到文件里
        ret = splice(pipefd[0], NULL, fd, NULL, splice_byte, SPLICE_F_MOVE | SPLICE_F_MORE);

        download_size += ret;
        if (download_size - last_size > slipce_size)
        {
            printf("%6.2lf%%\r", (double)download_size / file_size * 100);
            fflush(stdout);
            last_size = download_size;
        } 
    }

    gettimeofday(&end, NULL);
    printf("use time = %ld\n", (end.tv_sec - start.tv_sec) * 1000000 + end.tv_usec - start.tv_usec);
    close(fd);
    return 0;
}

// 发送文件
int upload_file(int remote_fd, const char *file_name)
{
    // 1. 发送文件名
    train_t t;
    t.data_len = strlen(file_name);
    strcpy(t.buf, file_name);
    send_n(remote_fd, &t, 4 + t.data_len);

    // 2. 发送文件大小
    struct stat file_info;
    stat(file_name, &file_info);
    t.data_len = sizeof(file_info.st_size);
    memcpy(t.buf, &file_info.st_size, sizeof(file_info.st_size));
    send_n(remote_fd, &t, 4 + t.data_len);

    // 3. 发送文件内容
    int fd = open(file_name, O_RDONLY);
    sendfile(remote_fd, fd, NULL, file_info.st_size);

    return 0;
}

int recv_n(int sfd, void* buf, int data_len)
{
    char *p = (char *)buf;
    int total = 0, ret;

    while (total < data_len)
    {
        ret = recv(sfd, p + total, data_len - total, 0);
        if (ret == 0) // 服务器断开
        {
            return -1;
        }
        total += ret;
    }
    return 0;
}

int send_n(int sfd, void* buf, int data_len)
{
    char *p = (char *)buf;
    int total = 0, ret;

    while (total < data_len)
    {
        ret = send(sfd, p + total, data_len - total, 0);
        if (ret == -1) // 客户端断开
        {
            return -1;
        }
        total += ret;
    }
    return 0;
}
